
type type_t = string

type t =
    Const of Const.t
  | Id of string
  | Cast of string * t
  | FieldAccess of t * string
  | MethodCall of t * string * t list
  | StaticCall of string * string * t list
  | Let of (string * t) list * t
  | New of (string * string * t list) list * t
  | If of t * t * t

type qualifier_t = Instance | Static

type method_t =
    Method of qualifier_t * type_t * string * (type_t * string) list * t option

type class_t =
    Class of string * string * (type_t * string) list * method_t list

let get_class_name (Class (class_name, _, _, _)) = class_name
let get_field_type (Class (_, _, fields, _)) name = List.assoc name (List.map (fun (x, y) -> (y, x)) fields) 


module OrderedString =
struct
  type t = string
  let compare = Pervasives.compare
end

module StringSet = Set.Make(OrderedString)

let dependencies (Class (cls, base, fields, methods)) =
  let rec aux_decls fields = aux_list (List.map aux_decl fields)
  and aux_methods methods = aux_list (List.map aux_method methods)
  and aux_decl (cls, _) = StringSet.singleton cls
  and aux_method (Method (_, cls, _, args, body_opt)) =
    StringSet.add cls (StringSet.union (aux_decls args) (aux_expr_opt body_opt))
  and aux_expr_opt =
    function
	None -> StringSet.empty
      | Some expr -> aux_expr expr
  and aux_expr =
    function
	Const _
      | Id _ -> StringSet.empty
      | Cast (cls, expr) -> StringSet.add cls (aux_expr expr)
      | FieldAccess (expr, _) -> aux_expr expr
      | MethodCall (expr, _, exprs) -> StringSet.union (aux_expr expr) (aux_expr_list exprs)
      | StaticCall (cls, _, exprs) -> StringSet.add cls (aux_expr_list exprs)
      | Let (bindings, expr) -> StringSet.union (aux_bindings bindings) (aux_expr expr)
      | New (specs, expr) -> StringSet.union (aux_news specs) (aux_expr expr)
      | If (expr1, expr2, expr3) -> StringSet.union (aux_expr expr1) (StringSet.union (aux_expr expr2) (aux_expr expr2))
  and aux_expr_list exprs = aux_list (List.map aux_expr exprs)
  and aux_bindings bindings = aux_list (List.map aux_binding bindings)
  and aux_news specs = aux_list (List.map aux_new specs)
  and aux_binding (_, expr) = aux_expr expr
  and aux_new (_, cls, exprs) = StringSet.add cls (aux_expr_list exprs)
  and aux_list ss = List.fold_left StringSet.union StringSet.empty ss
  in
    StringSet.elements (StringSet.remove cls (StringSet.add base (StringSet.union (aux_decls fields) (aux_methods methods))))

(*

 prova in Ocaml

#load "const.cmo";;
#load "ast.cmo";;
#load "astO.cmo";;
#load "compiler.cmo";;
#load "lexer.cmo";;
#load "parser.cmo";;
let lexbuf = Lexing.from_channel stdin;;
let g = Parser.main Lexer.token lexbuf;;

let a = 3 in
let b = 6 in
let f = fun  x y -> x + y in
let g = fun  c d -> c * d in
let h = fun  e f -> e / f in
(f (g a b) a)
;;

*)






					       
					       
